<template>
  <view class="audio-box">
    <view class="audio-left">
      <view class="audio-middle">
        <view class="audio-header">
          <text class="audio-title line-1">{{ title }}</text>
          <text class="audio-time">- {{ leftTime }}</text>
        </view>

        <!-- 调速拉条区 -->
        <view class="audio-progress">
          <image src="./icon/get-back.svg" @click="onSeek(-15)" />
          <view class="audio-bar">
            <slider
              class="audio-slider"
              :value="currentTime"
              :min="0"
              :max="duration"
              @change="sliderChange"
              @changing="sliderChanging"
              activeColor="#00CA86"
              backgroundColor="#475266"
              block-color="#fff"
              block-size="17"
            />
          </view>
          <image src="./icon/fast-forward.svg" @click="onSeek(15)" />
        </view>
      </view>
    </view>
    <view class="audio-right">
      <view class="audio-poster" :class="{ gap: poster }">
        <image mode="fillFix" :src="poster" v-if="poster" />
      </view>
      <view
        class="play-btn"
        :style="{ backgroundColor: isPaused ? '#00CA86' : '#475266' }"
        @click="onPlayPause()"
      >
        <image v-show="isPaused" src="./icon/suspend.svg"></image>
        <image v-show="!isPaused" src="./icon/start.svg"></image>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
  import { onUnload } from '@dcloudio/uni-app';
  import { ref, nextTick, computed } from 'vue';
  const props = defineProps({
    src: {
      type: String,
      default: '',
    }, // 音源
    title: { type: String, default: '' }, // 标题
    poster: { type: String, default: '' }, // 封面
    loop: { type: Boolean, default: false }, // 循环播放
    autoplay: { type: Boolean, default: false }, // 自动播放
  });

  const isPaused = ref<boolean>(true); // 是否暂停中
  const duration = ref<number>(0); // 音频时长
  const currentTime = ref<number>(0); // 当前时长
  // const leftTime = ref<string>('00:00'); // 剩余时长
  const isSlidering = ref<boolean>(false); // 是否移动中

  const innerAudioContext = uni.createInnerAudioContext();
  const initConfig = () => {
    innerAudioContext.src = props.src;
    innerAudioContext.loop = props.loop;
    innerAudioContext.autoplay = props.autoplay;

    // 音频播放事件
    innerAudioContext.onPlay(() => {
      // console.log('开始播放');
      getDuration();
      uni.setKeepScreenOn({
        keepScreenOn: true,
      });
    });
    // 音频暂停事件
    innerAudioContext.onPause(() => {
      // console.log('暂停播放');
      uni.setKeepScreenOn({
        keepScreenOn: false,
      });
    });
    // 音频进入可以播放状态(初次载入视频或拖动时间轴滑块会触发该事件)
    innerAudioContext.onCanplay(() => {
      // console.log('onCanplay');
      getDuration();
    });

    // 音频自然播放结束事件
    innerAudioContext.onEnded(() => {
      // console.log('播放结束');
      isPaused.value = true;
      currentTime.value = 0;
      innerAudioContext.seek(0);
    });
    // 音频播放错误事件
    innerAudioContext.onError((res) => {
      console.log('音频播放错误事件', res);
      duration.value = 0;
      currentTime.value = 0;
      isPaused.value = true;
      innerAudioContext.pause();
    });
    // 音频播放进度更新事件
    innerAudioContext.onTimeUpdate((event) => setPlayTime(event));
  };

  nextTick(() => {
    initConfig();
    // 有时候获取不了duration的，需要播放才可以获取
    if (duration.value == 0) {
      console.log('播放获取duration');
      innerAudioContext.play();
      setTimeout(() => {
        innerAudioContext.pause();
      }, 300);
    }
  });

  onUnload(() => {
    innerAudioContext.destroy();
    uni.setKeepScreenOn({
      keepScreenOn: false,
    });
  });

  // 获取音频时长
  const getDuration = () => {
    if (duration.value > 0) return;
    let times = 0;
    let timer = setInterval(() => {
      times++;
      if (innerAudioContext.duration > 0) {
        duration.value = innerAudioContext.duration;
        clearInterval(timer);
        return;
      }
      if (times > 9) {
        clearInterval(timer);
        console.log('无法获取音频时长');
        return;
      }
    }, 500);
  };

  // 调整播放位置
  const onSeek = (num: number) => {
    if (!innerAudioContext.currentTime) return;
    let seekNum = num + innerAudioContext.currentTime;
    if (seekNum < 0) {
      // 调整后时间小于0
      currentTime.value = 0;
      innerAudioContext.seek(0);
    } else if (seekNum > innerAudioContext.duration) {
      // 调整后时间大于总时长
      currentTime.value = innerAudioContext.duration;
      innerAudioContext.seek(innerAudioContext.duration);
    } else {
      currentTime.value = seekNum;
      innerAudioContext.seek(seekNum);
    }
  };

  // 播放或暂停
  const onPlayPause = () => {
    isPaused.value ? innerAudioContext.play() : innerAudioContext.pause();
    isPaused.value = !isPaused.value;
  };

  // 滑块滚动到的位置
  const sliderChange = (event: any) => {
    // console.log('滑块移动结束:', event.detail.value);
    isSlidering.value = false;
    currentTime.value = event.detail.value;
    innerAudioContext.seek(event.detail.value);
  };

  // 滑块滚动到的位置 实时
  const sliderChanging = (event: any) => {
    // console.log('滑块移动中:', event.detail.value);
    isSlidering.value = true;
    currentTime.value = event.detail.value;
  };

  // 滑块持续滚动
  const setPlayTime = (event: any) => {
    if (isSlidering.value) return;
    if (!innerAudioContext.duration && !innerAudioContext.currentTime) return;
    currentTime.value = innerAudioContext.currentTime || 0;
    // console.log(leftTime.value);
  };

  // 剩余时长
  const leftTime = computed(() => {
    if (duration.value > currentTime.value) {
      return minTimeFmt(duration.value - currentTime.value);
    }
    return minTimeFmt(0);
  });

  const minTimeFmt = (val: number) => {
    let minute = Math.floor(val / 60);
    let seconds = Math.ceil(val % 60);
    return `${minute >= 10 ? minute : '0' + minute}:${seconds >= 10 ? seconds : '0' + seconds}`;
  };
</script>

<style lang="scss" scoped>
  .audio-box {
    display: flex;
    align-items: center;
    background: #fff;
    box-shadow: rgba(0, 0, 0, 0.08) 0px 6px 9px;

    .audio-left {
      display: flex;
      flex: 1;
      padding: 10rpx 0 10rpx 25rpx;

      .audio-middle {
        display: flex;
        flex-direction: column;
        flex: 1;

        .audio-header {
          display: flex;
          align-items: center;
          justify-content: space-between;
          margin: 2rpx 0 5rpx;

          .audio-title {
            font-size: 26rpx;
          }

          .audio-time {
            flex: none;
            font-size: 25rpx;
            color: #b1b1b1;
            width: 110rpx;
            text-align: right;
          }
        }
      }
    }

    .audio-right {
      position: relative;
      .audio-poster {
        width: 140rpx;
        height: 120rpx;

        image {
          width: 100%;
          height: 100%;
          filter: brightness(80%);
        }
      }

      .gap {
        margin-left: 20rpx;
      }

      .play-btn {
        position: absolute;
        top: 30rpx;
        right: 40rpx;
        width: 60rpx;
        height: 60rpx;
        border-radius: 50%;

        image {
          width: 60rpx;
          height: 60rpx;
        }
      }
    }
  }

  .audio-progress {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 5rpx;

    image {
      width: 45rpx;
      height: 45rpx;
    }

    .audio-bar {
      flex: 1;
      padding: 0 26rpx;
      box-sizing: border-box;

      .audio-slider {
        margin: 0;
      }
    }
  }
</style>
